//#ifdef __M_SERVER_H__
#define __M_SERVER_H__
#include <iostream>
#include <vector>
#include <cassert>
#include <cstring>
#include <ctime>
#include <thread>
#include <unistd.h>
#include <unordered_map>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/timerfd.h>
#include <sys/eventfd.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <mutex>
#include <condition_variable>

#define INF 0
#define DBG 1
#define ERR 2
#define LOG_LEVEL DBG

#define LOG(level, format, ...) do{\
        if (level < LOG_LEVEL) break;\
        time_t t = time(NULL);\
        struct tm *ltm = localtime(&t);\
        char tmp[32] = {0};\
        strftime(tmp, 31, "%H:%M:%S", ltm);\
        fprintf(stdout, "[%p %s %s:%d] " format "\n", (void*)pthread_self(), tmp, __FILE__, __LINE__, ##__VA_ARGS__);\
    }while(0)

#define INF_LOG(format, ...) LOG(INF, format, ##__VA_ARGS__)
#define DBG_LOG(format, ...) LOG(DBG, format, ##__VA_ARGS__)
#define ERR_LOG(format, ...) LOG(ERR, format, ##__VA_ARGS__)

#define BUFFER_DEFAULT_SIZE 1024
class Buffer
{
    private:
        std::vector<char> _buffer; // 用vector充当缓冲区
        uint64_t _reader_idx; // 读偏移的位置
        uint64_t _writer_idx; // 写偏移的位置;
    public:
        Buffer(): _buffer(BUFFER_DEFAULT_SIZE),_reader_idx(0),_writer_idx(0){}
        char* BeGin() {return &*_buffer.begin(); }
        //获取当前写位置的地址,先解引用迭代器然后再取地址返回
        char* WritePosition() {return &*(_buffer.begin() + _writer_idx); }
        //获取当前读位置地址，同理
        char* ReadPosition() {return &*(_buffer.begin() + _reader_idx); }
        // 获取末尾空闲空间大小
        uint64_t TailIdleSize() {return _buffer.size() - _writer_idx; }
        // 获取前端空间大小
        uint64_t HeadIdleSize() {return  _reader_idx; }
        // 获取当前可读空间的大小
        uint64_t ReadAbleSize() {return _writer_idx - _reader_idx; }
        // 将读偏移向后移动len长度
        void MoveReadOffset(uint64_t len)
        {
            if(len <= 0) return;
            // 偏移量必须小于可读空间
            assert(len <= ReadAbleSize());
            _reader_idx += len;
        }
        // 将写偏移向后移动len长度
        void MoveWriteOffset(uint64_t len)
        {
            if(len <= 0) return;
            // 偏移量必须小于后端空间大小
            assert(len <= TailIdleSize());
            _writer_idx += len;
        }
        // 确保 整体 空间足够（包括移动数据和扩容）
        void EnsureWriteSpace(uint64_t len)
        {
            // 如果后端空闲空间大小够了就直接返回，不需要其他操作
            if(TailIdleSize() > len) return; 

            if(HeadIdleSize() + TailIdleSize() < len) // 扩容
            {
                DBG_LOG("RESIZE %ld",_writer_idx + len);
                _buffer.resize(_writer_idx + len); // 确保扩容后能装下len长度
            }
            else 
            {
                // 走到这里说明整体空间够，但是后端不够了，那么就移动数据，将数据移动到数组的开头
                uint64_t rsz = ReadAbleSize();
                std::copy(ReadPosition(),ReadPosition() + rsz,BeGin());
                _reader_idx = 0;
                _writer_idx = rsz;
            }
        }
        // 写入数据
        void Write(const void* data,uint64_t len)
        {
            if(len <= 0) return;
            // 先确保空间足够
            EnsureWriteSpace(len);
            const char* d = (const char*)data;
            std::copy(d,d + len,WritePosition());
        }
        // 写入数据并保存
        void WriteAndPush(const void* data,uint64_t len)
        {
            Write(data,len);
            MoveWriteOffset(len);
        }
        // 用string类型直接写入
        void WriteString(const std::string& data)
        {   Write(data.c_str(),data.size()); }
        // 同理保存
        void WriteStringAndPush(const std::string& data)
        {  WriteAndPush(data.c_str(),data.size()); }
        // 用Buffer类直接写入
        void WriteBuffer(Buffer& data)
        {   Write(data.ReadPosition(),data.ReadAbleSize()); }
        // 同理保存   
        void WriteBufferAndPush(Buffer& data)
        {   WriteAndPush(data.ReadPosition(),data.ReadAbleSize()); }
        // 读取数据
        void Read(void* buf,uint64_t len)
        {
            if(len <= 0) return;
            // 读取长度必须小于当前可读取的大小
            assert(len <= ReadAbleSize());
            std::copy(ReadPosition(),ReadPosition() + len,(char*)buf);
        }
        // 读取并清除数据
        void ReadAndPop(void* buf,uint64_t len)
        {
            Read(buf,len);
            MoveReadOffset(len);
        }
        // 将读取的数据以string类型返回
        std::string ReadString(uint64_t len)
        {
            assert(len <= ReadAbleSize());
            std::string str;
            str.resize(len);
            Read(&str[0],len);
            return str;
        }
        // 读取并清除
        std::string ReadStringAndPop(uint64_t len)
        {
            assert(len <= ReadAbleSize());
            std::string str = ReadString(len);
            MoveReadOffset(len);
            return str;
        }
        // 寻找换行符
        char* FindCRLF()
        {
            char* res = (char*)memchr(ReadPosition(),'\n',ReadAbleSize());
            return res;
        }
        // 获取一行数据
        std::string GetLine()
        {
            char* pos = FindCRLF();
            if(pos == nullptr)
                return "";
            // +1 是为了将换行符也提取出来
            return ReadString(pos - ReadPosition() + 1);
        }
        // 获取一行并清除数据
        std::string GetLineAndPop()
        {
            std::string str = GetLine();
            MoveReadOffset(str.size());
            return str;
        }
        //清空缓冲区
        void Clear()
        {
            // 只需要将偏移量置为0即可
            _reader_idx = 0;
            _writer_idx = 0;
        }
};

// 用来创建并管理套接字
// 主线程用它来创建监听套接字，并用它来进行监听
// 将监听到的套接字的fd用来实例化Socket对象，每一个连接都要用到Socket对连接文件描述符fd进行管理
#define MAX_LISTEN 1024
class Socket
{
    private:
        int _socketfd;
    public:
        Socket() :_socketfd(-1){}
        Socket(int fd) : _socketfd(fd){}
        ~Socket(){ Close(); }
        int Fd() { return _socketfd;}
        // 关闭套接字
        void Close()
        {
            if(_socketfd != -1)
            {
                close(_socketfd);
                _socketfd = -1;
            }
        }
        // 创建套接字
        bool Create()
        {
            // int socket(int domain, int type, int protocol)
            _socketfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
            if(_socketfd < 0)
            {
                ERR_LOG("GREATE SOCKET FAILED!");
                return false;
            }
            return true;
        }
        // 绑定地址信息
        bool Bind(const std::string& ip,uint16_t port)
        {
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(port);
            addr.sin_addr.s_addr = inet_addr(ip.c_str());
            socklen_t len = sizeof(struct sockaddr_in);
            // int bind(int sockfd, struct sockaddr*addr, socklen_t len);
            int ret = bind(_socketfd,(struct sockaddr*)&addr,len);
            if(ret < 0)
            {
                ERR_LOG("Bind Failed!");
                return false;
            }
            return true;
        }
        // 监听
        bool Listen(int backlog = MAX_LISTEN)
        {
            // int listen(int _fd,int backlog)
            int ret = listen(_socketfd,backlog);
            if(ret < 0)
            {
                ERR_LOG("Listen Failed!");
                return false;
            }
            return true;
        }
        // 向服务器发起连接
        bool Connect(const std::string& ip,uint16_t port)
        {
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(port);
            addr.sin_addr.s_addr = inet_addr(ip.c_str());
            socklen_t len = sizeof(struct sockaddr_in);
            // int connect(int sockfd, struct sockaddr*addr, socklen_t len);
            int ret = connect(_socketfd,(struct sockaddr*)&addr,len);
            if(ret < 0)
            {
                ERR_LOG("Connect Server Failed!");
                return false;
            }
            return true;
        }
        // 获取新链接
        int Accept()
        {
            // int accept(int sockfd, struct sockaddr *addr, socklen_t *len);
            int newfd = accept(_socketfd,NULL,NULL);
            if(newfd < 0)
            {
                ERR_LOG("Accept failed!");
                return -1;
            }
            return newfd;
        }
        // 接收数据
        ssize_t Recv(void* buf,ssize_t len,int flag = 0)
        {
            // ssize_t recv(int sockfd, void *buf, size_t len, int flag);
            ssize_t ret = recv(_socketfd,buf,len,flag);
            if(ret <= 0)
            {
                //EAGAIN 当前socket的接收缓冲区中没有数据了，在非阻塞的情况下才会有这个错误
                //EINTR  表示当前socket的阻塞等待，被信号打断了。
                if(errno == EAGAIN || errno == EINTR)
                {
                    return 0; // 表示这次没有接收到数据，不算出错
                }
                //到这里表示出错了
                ERR_LOG("Recv Failed!");
                return -1;
            }
            return ret; // 实际接收数据的长度
        }
        //非阻塞接收数据
        ssize_t NonBlockRecv(void* buf,ssize_t len)
        {
            return Recv(buf,len,MSG_DONTWAIT); // MSG_DONTWAIT 表示当前接收为非阻塞。
        }
        // 发送数据
        ssize_t Send(const void* buf,ssize_t len,int flag = 0)
        {
            // ssize_t send(int sockfd, void *data, size_t len, int flag);
            int ret = send(_socketfd,buf,len,flag);
            if(ret < 0)
            {
                if(errno == EAGAIN | EINTR)
                {
                    return 0;
                }
                //到这里表示出错了
                ERR_LOG("Send Failed!");
                return -1;
            }
            return ret; // 实际发送出去的数据长度
        }
        // 非阻塞发送数据
        ssize_t NonBlockSend(const void* buf,ssize_t len)
        {
            return Send(buf,len,MSG_DONTWAIT); // MSG_DONTWAIT 表示当前发送为非阻塞。
        }
        // 设置套接字阻塞属性 -- 设置为非阻塞
        void NonBlock()
        {
            //int fcntl(int fd, int cmd, ... /* arg */ );
            int flag = fcntl(_socketfd,F_GETFL,0);
            fcntl(_socketfd,F_SETFL,flag | O_NONBLOCK);
        }
        //设置套接字选项---开启地址端口重用
        void ReuseAddress()
        {
            // int setsockopt(int fd, int leve, int optname, void *val, int vallen)
            int opt = 1;
            // 设置ip地址重用
            setsockopt(_socketfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt));
            opt = 1;
            // 设置端口号重用
            setsockopt(_socketfd,SOL_SOCKET,SO_REUSEPORT,(void*)&opt,sizeof(opt));
        }
        // 创建服务端连接
        bool CreateServer(uint16_t port,const std::string& ip = "0.0.0.0",bool block_flag = false)
        {
            //1. 创建套接字，2. 绑定地址，3. 开始监听，4. 设置非阻塞， 5. 启动地址重用
            if(Create() == false) return false;
            if(Bind(ip,port) == false) return false;
            if(Listen() == false) return false;
            if(block_flag) NonBlock();
            ReuseAddress();
            return true;
        }
        // 创建客户端连接
        bool CreateClient(uint16_t port,const std::string& ip)
        {
            //1. 创建套接字，2.指向连接服务器   
            if(Create() == false) return false;
            if(Connect(ip,port) == false) return false;
            return true;
        }
};

class Poller;
class EventLoop;
// 对事件的监控，以及触发事件后的回调函数
class Channel 
{
    private:
        int _fd;
        EventLoop* _loop;
        uint32_t _events;  // 当前需要监控的事件（比如读或者写之类的）
        uint32_t _revents; // 当前连接触发的事件
        using EventCallback = std::function<void()>; 
        EventCallback _read_callback;   //可读事件被触发的回调函数
        EventCallback _write_callback;  //可写事件被触发的回调函数
        EventCallback _error_callback;  //错误事件被触发的回调函数
        EventCallback _close_callback;  //连接断开事件被触发的回调函数
        EventCallback _event_callback;  //任意事件被触发的回调函数
    public:
        Channel(EventLoop* loop,int fd) :_fd(fd), _loop(loop), _events(0), _revents(0) {}
        int Fd() { return _fd; };
        uint32_t Events() { return _events; } // 获取想要监控的事件
        void SetREvents(uint32_t events) { _revents = events; } // 设置就绪的事件
        // 设置一系列回调函数
        void SetReadCallback (const EventCallback& cb) { _read_callback = cb; }
        void SetWriteCallback(const EventCallback &cb) { _write_callback = cb; }
        void SetErrorCallback(const EventCallback &cb) { _error_callback = cb; }
        void SetCloseCallback(const EventCallback &cb) { _close_callback = cb; }
        void SetEventCallback(const EventCallback &cb) { _event_callback = cb; }
        // 当前是否监控了可读
        bool ReadAble() { return _events & EPOLLIN; }
        // 当前是否监控了可写
        bool WriteAble() { return _events & EPOLLOUT; }
        // 启动读事件监控
        void EnableRead() { _events |= EPOLLIN; Update(); }
        // 启动写事件监控
        void EnableWrite() { _events |= EPOLLOUT; Update(); }
        // 关闭读事件监控
        void DisableRead() { _events &= ~EPOLLIN; Update(); }
        // 关闭写事件监控
        void DisableWrite() { _events &= ~EPOLLOUT; Update(); }
        // 关闭所有事件监控
        void DisableAll() { _events = 0; Update(); }
        //移除监控
        void Remove();
        void Update();
        // 一旦事件触发，就调用的函数,根据类型再选择如何处理
        void HandleEvent()
        {
            if((_revents & EPOLLIN) || (_revents & EPOLLHUP) || (_revents & EPOLLPRI))
            {
                // 不管任何事件都要调用的回调函数
                if(_read_callback) _read_callback();
            }
            // 有可能会释放连接的操作，一次只处理一个
            if(_revents & EPOLLOUT)
            {
                if(_write_callback) _write_callback();
            }
            else if(_revents & EPOLLERR)
            {
                if(_error_callback) _error_callback();//一旦出错，就会释放连接，因此要放到前边调用任意回调
            }
            else if(_revents & EPOLLHUP)
            {
                if(_close_callback) _close_callback();
            }
            // 虽然上述的操作可能会导致连接被释放，但是它们调用的释放接口Release只是把ReleaseInLoop压入到任务队列中
            // 并不是直接的释放，所以我们可以把任意事件回调放在最后，这样用来刷新活跃度也显得合理了一些。
            if (_event_callback) _event_callback();
        }
};

#define MAX_EPOLLEVENTS 1024
// 封装了对epoll的直接操作，在这里面用哈希表对Channel们进行了管理
// 每一个Channel都会关联上Poller，并把自己需要监控的事件交给Poller然后让其进行监控
// 每一次监控都是阻塞式的，每一次用一个数组监控多个Channel
// 当某个Channel事件就绪后，会把它的Channel指针放入到一个数组中，并将这个Channel的就绪事件情况设置好
// Poller是EventLoop模块的子模块，在EventLoop中会调用Poller的Poll()进行监控，将返回得到的数组拿到后
// 会对数组里面的Channel一个一个的进行处理，比如调用任意事件触发的回调函数（刷新活跃度），并执行对应回调函数
class Poller
{
    private:
        int _epfd;
        struct epoll_event _evs[MAX_EPOLLEVENTS];
        std::unordered_map<int,Channel*> _channels;
    private:
        // 对epoll的直接操作
        void Update(Channel *channel, int op)
        {
            // int epoll_ctl(int epfd, int op,  int fd,  struct epoll_event *ev);
            int fd = channel->Fd();
            struct epoll_event ev;
            ev.data.fd = fd;
            ev.events = channel->Events();
            int ret = epoll_ctl(_epfd,op,fd,&ev);
            if(ret < 0)
            {
                ERR_LOG("EpollCtl Failed! ");
            }
            return;
        }
        // 判断一个Channel是否已经添加了事件监控
        bool HasChannel(Channel *channel)
        {
            auto it = _channels.find(channel->Fd());
            if(it == _channels.end())
            {
                return false;
            }
            return true;
        }
    public:
        Poller()
        {
            _epfd = epoll_create(MAX_EPOLLEVENTS);
            if(_epfd < 0)
            {
                ERR_LOG("Epoll Create Failed! ");
                abort(); // 直接退出程序
            }
        }
        // 添加或者修改事件监控
        void UpdateEvent(Channel *channel)
        {
            bool ret = HasChannel(channel);
            if(ret == false)
            {
                // 不存在就添加
                _channels.insert(std::make_pair(channel->Fd(),channel));
                Update(channel,EPOLL_CTL_ADD);
            }
            Update(channel,EPOLL_CTL_MOD);
        }
        // 移除事件监控
        void RemoveEvent(Channel* channel)
        {
            auto it = _channels.find(channel->Fd());
            if(it != _channels.end())
            {
                _channels.erase(it);
            }
            Update(channel,EPOLL_CTL_DEL);
        }
        // 开始监控，返回活跃连接
        void Poll(std::vector<Channel*>* active)
        {
            // int epoll_wait(int epfd, struct epoll_event *evs, int maxevents, int timeout)
            int nfds = epoll_wait(_epfd,_evs,MAX_EPOLLEVENTS,-1); // 阻塞的
            if(nfds < 0)
            {
                if(errno == EINTR)
                {
                    return;
                }
                ERR_LOG("Epoll Wait ERROR: %s\n",strerror(errno));
                abort();
            }
            for(int i = 0; i < nfds; ++i)
            {
                auto it = _channels.find(_evs[i].data.fd);
                assert(it != _channels.end());
                it->second->SetREvents(_evs[i].events); // 设置实际就绪的事件
                active->push_back(it->second);
            }
            return;
        }
};

using TaskFunc = std::function<void()>;
using ReleaseFunc  = std::function<void()>;
class TimerTask
{
    private:
        uint64_t _id; // 定时器对象任务id
        uint32_t _timeout; // 定时器任务超时时间
        bool _canceled; // false表示任务没有取消，true表示被取消。
        TaskFunc _task_cb; // 定时器任务回调函数
        ReleaseFunc _release; // 用于删除timeWheel中保存的定时器任务信息
    public:
        TimerTask(uint64_t id,uint32_t delay,const TaskFunc& cb):
        _id(id), _timeout(delay), _task_cb(cb), _canceled(false) {}
        ~TimerTask()
        {
            if(_canceled == false) 
            {
                _task_cb();
            }
            _release();
        }
        void Cancel() { _canceled = true; }
        void SetRelease(const ReleaseFunc& cb) { _release = cb; }
        uint32_t DelayTime() { return _timeout; }
};

class TimerWheel 
{
    private:
        using WeakTask = std::weak_ptr<TimerTask>;
        using PtrTask = std::shared_ptr<TimerTask>;
        int _tick; // 相当于秒针，走到哪就执行到哪的任务。
        int _capacity; // 表盘的最大数量，也就是最大的延迟时间
        std::vector<std::vector<PtrTask>> _wheel; // 二维数组，遍历用的
        std::unordered_map<uint64_t, WeakTask> _timers; // 用哈希表把时间轮里的任务管理起来

        EventLoop* _loop;
        int _timerfd;//定时器描述符--可读事件回调就是读取计数器，执行定时任务
        std::unique_ptr<Channel> _timer_channel; // 也用Channel管理起来
    private:
        // 根据任务id从哈希表中删除任务
        void RemoveTimer(uint64_t id)
        {
            auto it = _timers.find(id);
            if(it != _timers.end())
            {
                _timers.erase(it);
            }
        }
        // 创建定时器文件描述符，并设置超时时间
        static int CreateTimerfd()
        {
            int timerfd = timerfd_create(CLOCK_MONOTONIC,0);
            if(timerfd < 0)
            {
                ERR_LOG("Timerfd Create Failed!");
                abort();
            }
            //int timerfd_settime(int fd, int flags, struct itimerspec *new, struct itimerspec *old);
            struct itimerspec itime;
            itime.it_value.tv_sec = 1;
            itime.it_value.tv_nsec = 0;//第一次超时时间为1s后
            itime.it_interval.tv_sec = 1; 
            itime.it_interval.tv_nsec = 0; //第一次超时后，每次超时的间隔时
            timerfd_settime(timerfd, 0, &itime, NULL);
            return timerfd;
        }
        int ReadTimefd()
        {
            uint64_t times;
            //有可能因为其他描述符的事件处理花费事件比较长，然后在处理定时器描述符事件的时候，有可能就已经超时了很多次
            //read读取到的数据times就是从上一次read之后超时的次数
            int ret = read(_timerfd,&times,8);
            if(ret < 0)
            {
                ERR_LOG("Read TimeFd Failed!");
                abort();
            }
            return times;
        }
        //这个函数应该每秒钟被执行一次，相当于秒针向后走了一步
        void RunTimerTask()
        {
            _tick = (_tick + 1) % _capacity;
             _wheel[_tick].clear();//清空指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉
        } 
        void OnTime()
        {
            //根据实际超时的次数，执行对应的超时任务
            int times = ReadTimefd();
            for(int i = 0; i < times; ++i)
            {
                RunTimerTask();
            }
        }
        // 添加任务到时间轮中
        void TimerAddInLoop(uint64_t id,uint32_t delay,const TaskFunc& cb)
        {
            PtrTask pt(new TimerTask(id, delay, cb));
            pt->SetRelease(std::bind(&TimerWheel::RemoveTimer,this,id));
            int pos = (_tick + delay) % _capacity;
            _wheel[pos].push_back(pt);
            _timers[id] = WeakTask(pt);
        }
        // 刷新定时任务
        void TimerRefreshInLoop(uint64_t id)
        {
            auto it = _timers.find(id);
            if(it == _timers.end())
            {
                // 没有找到该任务，无法刷新
                return;
            }
            PtrTask pt = it->second.lock();//lock获取weak_ptr管理的对象对应的shared_ptr
            int delay = pt->DelayTime();
            int pos = (_tick + delay) % _capacity;
            // 本质还是让shared_ptr里面的计数器+1，这样就可以延迟销毁
            _wheel[pos].push_back(pt);
        }
        // 取消定时任务
        void TimerCancelInLoop(uint64_t id)
        {
            auto it = _timers.find(id);
            if(it == _timers.end())
            {
                // 没有找到该任务，也就是谈不上取消
                return;
            }
            PtrTask pt = it->second.lock();
            pt->Cancel();
        }
    public:
        // 默认60秒的最大延迟
        TimerWheel(EventLoop* loop,int capacity = 60):
        _capacity(capacity), _tick(0), _wheel(_capacity),_loop(loop),
        _timerfd(CreateTimerfd()), _timer_channel(new Channel(_loop, _timerfd))
        {
            _timer_channel->SetReadCallback(std::bind(&TimerWheel::OnTime, this));
            _timer_channel->EnableRead();//启动读事件监控
        }
        /*定时器中有个_timers成员，定时器信息的操作有可能在多线程中进行，因此需要考虑线程安全问题*/
        /*如果不想加锁，那就把对定时器的所有操作，都放到一个线程中进行*/
        void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb);
        //刷新/延迟定时任务
        void TimerRefresh(uint64_t id);
        void TimerCancel(uint64_t id);
        /*这个接口存在线程安全问题--这个接口实际上不能被外界使用者调用，只能在模块内，在对应的EventLoop线程内执行*/
        bool HasTimer(uint64_t id) {
            auto it = _timers.find(id);
            if (it == _timers.end()) {
                return false;
            }
            return true;
        }
};

// 一个线程一个EventLoop
class EventLoop 
{
    private:
        using Functor = std::function<void()>;
        std::thread::id _thread_id; // 线程id
        int _event_fd; // eventfd唤醒IO事件监控有可能导致的阻塞
        std::unique_ptr<Channel> _event_channel; // 同样用Channel加智能指针管理起来
        Poller _poller; // 对所有的事件进行监控
        std::vector<Functor> _tasks; // 任务池
        std::mutex _mutex; // 用来保证任务池的线程安全
        TimerWheel _timer_wheel; // 定时器
    public:
        // 执行任务池中的所有任务
        void RunAllTask()
        {
            std::vector<Functor> functor;
            {
                // 作用域内加锁，出了作用域后释放
                std::unique_lock<std::mutex> _lock(_mutex);
                _tasks.swap(functor); // 用交换的方式把所有任务取出
            }
            for(auto& f : functor)
            {
                f();
            }
        }
        static int CreateEventFd()
        {
            uint64_t efd = 0;
            efd = eventfd(0,EFD_CLOEXEC | EFD_NONBLOCK);
            if(efd < 0)
            {
                ERR_LOG("Create EventFd Failed!");
                abort();
            }
            return efd;
        }
        void ReadEventfd()
        {
            uint64_t res = 0;
            int ret = read(_event_fd, &res, sizeof(res));
            if (ret < 0)
            {
                //EINTR -- 被信号打断；   EAGAIN -- 表示无数据可读
                if (errno == EINTR || errno == EAGAIN) 
                {
                    return;
                }
                ERR_LOG("READ EVENTFD FAILED!");
                abort();
            }
        }
        void WeakUpEventFd() 
        {
            uint64_t val = 1;
            int ret = write(_event_fd, &val, sizeof(val));
            if (ret < 0) 
            {
                if (errno == EINTR)
                {
                    return;
                }
                ERR_LOG("READ EVENTFD FAILED!");
                abort();
            }
            return ;
        }
    public:
        EventLoop(): _thread_id(std::this_thread::get_id()),
                    _event_fd(CreateEventFd()),
                    _event_channel(new Channel(this,_event_fd)),
                    _timer_wheel(this)
            {
                // 给eventfd添加可读事件回调函数，读取eventfd事件通知次数
                _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd,this));
                //启动eventfd的读事件监控
                _event_channel->EnableRead();
            }
        //三步走--事件监控-》就绪事件处理-》执行任务
        void Start()
        {
            while(1)
            {
                // 1.事件监控
                std::vector<Channel*> actives;
                _poller.Poll(&actives);
                // 2.处理就绪事件
                for(auto& channel : actives)
                {
                    channel->HandleEvent();
                }
                // 3.执行任务
                RunAllTask();
            }
        }
        // 判断当前线程是否是EventLoop对应的线程；
        bool IsInLoop()
        {
            return (_thread_id == std::this_thread::get_id());
        }
        void AssertInLoop()
        {
            assert(_thread_id == std::this_thread::get_id());
        }
        // 判断将要执行的任务是否处于当前线程中，如果是则执行，不是则压入队列。
        void RunInLoop(const Functor& cb)
        {
            if(IsInLoop())
            {
                cb();
            }
            else  
            {
                QueueInLoop(cb);
            }
        }
        // 将操作压入任务池中
        void QueueInLoop(const Functor& cb)
        {
            {
                std::unique_lock<std::mutex> _lock(_mutex);
                _tasks.push_back(cb);
            }
            //唤醒有可能因为没有事件就绪，而导致的epoll阻塞；
            //其实就是给eventfd写入一个数据，eventfd就会触发可读事件
            WeakUpEventFd();
        }
        //添加/修改描述符的事件监控
        void UpdateEvent(Channel* channel) { return _poller.UpdateEvent(channel); }
        //移除描述符的监控
        void RemoveEvent(Channel* channel) { return _poller.RemoveEvent(channel); }
        // 添加定时器
        void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb) { return _timer_wheel.TimerAdd(id,delay,cb); }
        // 刷新定时器任务
        void TimerRefresh(uint64_t id) { return _timer_wheel.TimerRefresh(id); }
        // 取消定时器任务
        void TimerCancel(uint64_t id) { return _timer_wheel.TimerCancel(id); }
        // 是否添加了定时器任务
        bool HasTimer(uint64_t id) { return _timer_wheel.HasTimer(id); }
};

// 实际实例化EventLoo是在这里面实例化的，因为要保证一个EvnetLoop要跟一个线程绑定
class LoopThread 
{
    private:
        /*互斥锁和条件变量用于实现_loop获取的同步关系，避免线程创建了，但是_loop还没有实例化之前去获取_loop*/
        std::mutex _mutex; //互斥锁
        std::condition_variable _cond; //条件变量
        EventLoop* _loop; //这是一个指针，对象要在线程内实例化
        std::thread _thread; //该EventLoop对应的线程
    private:
        /*实例化 EventLoop 对象，唤醒_cond上有可能阻塞的线程，并且开始运行EventLoop模块的功能*/
        void ThreadEntry()
        {
            EventLoop loop; // 在这里实例化了
            {
                //作用域内加锁，出作用域后就解锁
                std::unique_lock<std::mutex> lock(_mutex);
                _loop = &loop;
                // 记得唤醒
                _cond.notify_all();
            }
            _loop->Start(); // 这里已经是阻塞循环运行了
        }
    public:
        /*创建线程，设定线程入口函数*/
        LoopThread() : _loop(NULL),_thread(std::thread(&LoopThread::ThreadEntry,this)){}
        //返回当前线程关联的EventLoop对象指针
        EventLoop* GetLoop()
        {
            EventLoop *loop = NULL;
            {
                std::unique_lock<std::mutex> lock(_mutex);//加锁
                _cond.wait(lock, [&](){ return _loop != NULL; });//loop为NULL就一直阻塞
                loop = _loop;
            }
            return loop;
        }
};

class LoopThreadPool 
{
    private:
        int _thread_count; //从属线程的数量
        int _next_idx; //是下一个该被调用的从属线程的EventLoop对象指针的索引
        EventLoop* _baseloop; //主线程的EventLoop
        std::vector<LoopThread*> _threads;
        std::vector<EventLoop*> _loops;
    public:
        LoopThreadPool(EventLoop* baseloop) : _thread_count(0), _next_idx(0),_baseloop(baseloop) {}
        void SetThreadCount(int thread_count) { _thread_count = thread_count; }
        void Create()
        {
            if(_thread_count > 0)
            {
                _threads.resize(_thread_count );
                _loops.resize(_thread_count );
                for(int i = 0; i < _thread_count ; ++i)
                {
                    _threads[i] = new LoopThread();
                    _loops[i] = _threads[i]->GetLoop();
                }
            }
            return;
        }
        EventLoop* NextLoop()
        {
            if(_thread_count == 0)
            {
                return _baseloop;
            }
            
            _next_idx = (_next_idx + 1) % _thread_count;
            return _loops[_next_idx];
        }
};

class Any
{
    private:
        class holder 
        {
            public:
                virtual ~holder() {}
                virtual const std::type_info& type() = 0;
                virtual holder* clone() = 0;
        };

        template <class T>
        class placeholder : public holder
        {   public:
                placeholder (const T& val) : _val(val) {}
                // 获取子类保存数据对象的类型
                virtual const std::type_info& type() { return typeid(T); }
                // 针对当前的对象自身，克隆出一个新的对象
                virtual holder* clone() { return new placeholder(_val); }
            public:
                T _val;
        };
        holder* _content;
    public:
        Any() : _content(NULL) {}
        template <class T>
        Any (const T& val) : _content(new placeholder<T>(val)) {}
        Any (const Any& other) : _content(other._content == NULL ? NULL : other._content->clone()) {}
        ~Any() { delete _content; }
        Any& swap(Any& other)
        {
            std::swap(_content,other._content);
            return *this;
        }

        // 返回子类对象保存的数据的指针
        template <class T>
        T* get()
        {
            // 想要获取的数据类型，必须要和保存的数据类型一致
            assert(typeid(T) == _content->type());
            return &((placeholder<T>*)_content)->_val;
        }
        // 赋值运算符的重载函数
        template <class T>
        Any& operator=(const T& val)
        {
            // 为val构造一个临时的Any对象容器，然后用swap进行交换，出了这个函数作用域后原来的对象就会自动销毁
            Any(val).swap(*this);
            return *this;
        }
        Any& operator=(const Any& other)
        {
            Any(other).swap(*this);
            return *this;
        }
};

class Connection;
//DISCONECTED -- 连接关闭状态；   CONNECTING -- 连接建立成功-待处理状态
//CONNECTED -- 连接建立完成，各种设置已完成，可以通信的状态；  DISCONNECTING -- 待关闭状态
typedef enum { DISCONNECTED, CONNECTING, CONNECTED, DISCONNECTING}ConnStatu;
using PtrConnection = std::shared_ptr<Connection>;
// Connection是由智能指针管理的，所以在释放Connection的时候，只需要把有该Connection的指针全部清理掉就释放了
class Connection : public std::enable_shared_from_this<Connection>
{
    private:
        uint64_t _conn_id; // 连接的唯一id，便于连接的管理和查找
        //uint64_t _timer_id;   //定时器ID，必须是唯一的，这块为了简化操作使用conn_id作为定时器ID
        int _sockfd; // 连接关联的文件描述符
        bool _enable_inactive_release; // 连接是否启动非活跃销毁的判断标志，默认为false，即不销毁
        EventLoop* _loop; // 连接所关联的一个EventLoop 
        ConnStatu _statu; // 当前连接的状态
        Socket _socket; // 套接字模块的，用于套接字管理操作
        Channel _channel; // 连接的事件管理
        Buffer _in_buffer; // 输入缓冲区---从socket 读到的数据要放到这里里面
        Buffer _out_buffer; // 输出缓冲区--- 存放要发送给对方的数据
        Any _context; // 处理连接的上下文
        /*这四个回调函数，是让服务器模块来设置的（其实服务器模块的处理回调也是组件使用者设置的）*/
        /*换句话说，这几个回调都是组件使用者使用的*/

        using ConnectedCallback = std::function<void(const PtrConnection&)>;
        using MessageCallback = std::function<void(const PtrConnection&,Buffer&)>;
        using ClosedCallback = std::function<void(const PtrConnection&)>;
        using AnyEventCallback = std::function<void(const PtrConnection&)>;
        ConnectedCallback _connected_callback;
        MessageCallback _message_callback;
        ClosedCallback _closed_callback;
        AnyEventCallback _event_callback;
        /*组件内的连接关闭回调--组件内设置的，因为服务器组件内会把所有的连接管理起来，一旦某个连接要关闭*/
        /*就应该从管理的地方移除掉自己的信息*/
        ClosedCallback _server_closed_callback;
    private:
        // 五个channel事件的回调函数
        // 描述符可读事件触发后调用的函数，接收socket数据放到接收缓冲区中，然后调用_message_callback
        void HandleRead()
        {
            // 1.接收socket的数据，放入到缓冲区中
            char buf[65536]; // 比65535多1是因为最后一个要放 \n 结尾
            ssize_t ret = _socket.NonBlockRecv(buf,65535);
            if(ret < 0)
            {
                // 出错了，但还不能直接关闭
                return ShutdownInLoop();
            }
            //这里的等于0表示的是没有读取到数据，而并不是连接断开了，连接断开返回的是-1
            //将数据放入输入缓冲区,写入之后顺便将写偏移向后移动
            _in_buffer.WriteAndPush(buf,ret);
            // 2.调用message_callback进行业务处理
            if(_in_buffer.ReadAbleSize() > 0)
            {
                //shared_from_this--从当前对象自身获取自身的shared_ptr管理对象
                // 如果要使用它，需要先让该类继承std::enable_shared_from_this<Connection>
                return _message_callback(shared_from_this(),_in_buffer);
            }
        }
        //描述符可写事件触发后调用的函数，将发送缓冲区中的数据进行发送
        void HandleWrite()
        {
            //_out_buffer中保存的数据就是要发送的数据
            ssize_t ret = _socket.NonBlockSend(&_out_buffer,_out_buffer.ReadAbleSize());
            if(ret < 0)
            {
                // 发送错误就关闭连接
                // 但是如果还有数据未处理需要先处理再关闭
                if(_in_buffer.ReadAbleSize() > 0)
                {
                    _message_callback(shared_from_this(),_in_buffer);
                }
                return Release(); // 实际的关闭操作
            }
            _out_buffer.MoveReadOffset(ret); // 记得将读偏移进行移动
            if(_out_buffer.ReadAbleSize() == 0)
            {
                // 将数据全部发送完后，关闭写事件监控
                _channel.DisableWrite();
                // 如果当前的连接状态是待关闭状态，那么发送完数据后就可以关闭了
                if(_statu == DISCONNECTING)
                {
                    return Release();
                }
            }
            // 到这里就是正常退出
            return;
        }
        // 描述符挂断事件
        void HandleClose()
        {
            // 如果此时连接已经挂断了，那么这个连接就什么也做不了了，只需要把读缓冲区里的数据处理一下就行了
            if(_in_buffer.ReadAbleSize() > 0)
            {
                _message_callback(shared_from_this(),_in_buffer);
            }
            return Release();
        }
        // 描述符触发错误事件
        void HandleError()
        {
            // 错误了就直接等于挂断
            return HandleClose();
        }
        //描述符触发任意事件: 1. 刷新连接的活跃度--延迟定时销毁任务；  2. 调用组件使用者的任意事件回调
        void HandleEvent()
        {
            if(_enable_inactive_release == true) _loop->TimerRefresh(_conn_id);
            if(_event_callback) _event_callback(shared_from_this());
        }
        //接下的----InLoop接口都是要在一个EvnetLoop（也就是同一个线程中）中执行的。
        //连接获取之后，所处的状态下要进行各种设置,也就是初始化（启动读监控,调用回调函数）
        void EstablishedInLoop()
        {
            // 1. 修改连接状态；  2. 启动读事件监控；  3. 调用回调函数
            assert(_statu == CONNECTING);//当前的状态必须一定是上层的半连接状态
            _statu = CONNECTED; // 执行完该函数，那么连接就处于上层的连接状态。
            // 一旦启动读事件监控就有可能会立即触发读事件，如果这时候启动了非活跃连接销毁
            _channel.EnableRead();
            if(_connected_callback) _connected_callback(shared_from_this());
        }
        // 实际释放连接的接口
        void ReleaseInLoop()
        {
            //1. 修改连接状态，将其置为DISCONNECTED
            _statu = DISCONNECTED;
            // 2.移除连接的所有事件监控
            _channel.Remove();
            // 3.关闭描述符
            _socket.Close();
            // 4.如果当前定时器任务队列中还有定时销毁任务，那么需要取消
            if(_loop->HasTimer(_conn_id)) _loop->TimerCancel(_conn_id);
            //5. 调用关闭回调函数，避免先移除服务器管理的连接信息导致Connection被释放，再去处理会出错，因此先调用用户的回调函数
            if(_closed_callback) _closed_callback(shared_from_this());
            //移除服务器内部管理的连接信息
            if(_server_closed_callback) _server_closed_callback(shared_from_this());
        }
        //这个接口并不是实际的发送接口，而只是把数据放到了发送缓冲区，启动了可写事件监控
        void SendInLoop(Buffer& buf)
        {
            if(_statu == DISCONNECTED) return; // 如果连接已经关闭，直接返回
            _out_buffer.WriteBufferAndPush(buf);
            // 如果没有启动写事件监控，那么就启动
            if(_channel.WriteAble() == false) _channel.EnableWrite();
        }
        //这个关闭操作并非实际的连接释放操作，需要判断还有没有数据待处理，待发送
        void ShutdownInLoop()
        {
            _statu = DISCONNECTING;
            if(_in_buffer.ReadAbleSize() > 0)
            {
                if(_message_callback) _message_callback(shared_from_this(),_in_buffer);
            }
            // 处理待写入的数据时，如果写入时出错会关闭连接，如果没有待写入的数据了，也会直接关闭
            if(_out_buffer.ReadAbleSize() > 0)
            {
                if(_channel.WriteAble() == false) _channel.EnableWrite();
            }
            if(_out_buffer.ReadAbleSize() == 0) Release();
        }
        //启动非活跃连接超时释放
        void EnableInactiveReleaseInLoop(int sec)
        {
            //1. 将判断标志 _enable_inactive_release 置为true
            _enable_inactive_release = true;
            //2. 如果当前定时销毁任务已经存在，那就刷新延迟一下即可
            if(_loop->HasTimer(_conn_id)) return _loop->TimerRefresh(_conn_id);
            //3.如果不存在就新增一个定时销毁任务
            _loop->TimerAdd(_conn_id,sec,std::bind(&Connection::Release,this));
        }
        // 取消非活跃销毁
        void CancelInactiveReleaseInLoop()
        {
            _enable_inactive_release = false;
            if(_loop->HasTimer(_conn_id)) _loop->TimerCancel(_conn_id);
        }
        // 切换协议---其实就是切换上下文和回调函数
        void UpgradeInLoop(const Any &context, 
                    const ConnectedCallback &conn, 
                    const MessageCallback &msg, 
                    const ClosedCallback &closed, 
                    const AnyEventCallback &event) 
        {
            _context = context;
            _connected_callback = conn;
            _message_callback = msg;
            _closed_callback = closed;
            _event_callback = event;
        }
    public:
        Connection(EventLoop* loop,uint64_t conn_id,int socketfd) : _conn_id(conn_id),_loop(loop),
                    _enable_inactive_release(false),_sockfd(socketfd),_statu(CONNECTING),_socket(socketfd),
                    _channel(loop,socketfd)
        {
            _channel.SetCloseCallback(std::bind(&Connection::HandleClose,this));
            _channel.SetEventCallback(std::bind(&Connection::HandleEvent, this));
            _channel.SetReadCallback(std::bind(&Connection::HandleRead, this));
            _channel.SetWriteCallback(std::bind(&Connection::HandleWrite, this));
            _channel.SetErrorCallback(std::bind(&Connection::HandleError, this));
        }
        ~Connection() { DBG_LOG("Release Connection : %p",this); }
        //获取管理的文件描述符
        int Fd() { return _sockfd; }
        //获取连接id
        int Id() {return _conn_id; }
        //是否处于CONNECTED状态
        bool Connected() { return _statu == CONNECTED; }
        //设置上下文，在连接建立完成时调用
        void SetContext(const Any& context) { _context = context; }
        // 获取上下文的指针
        Any* GetContext() { return &_context; }
        void SetConnectedCallback(const ConnectedCallback& cb) { _connected_callback = cb; }
        void SetMessageCallback(const MessageCallback& cb) { _message_callback = cb; }
        void SetClosedCallback(const ClosedCallback& cb) { _closed_callback = cb; }
        void SetAnyEventCallback(const AnyEventCallback& cb) { _event_callback = cb; }
        void SetSrvClosedCallback(const ClosedCallback& cb) { _server_closed_callback = cb; }
        //连接建立就绪后，进行channel回调设置，启动读监控，调用_connected_callback
        void Established() { _loop->RunInLoop(std::bind(&Connection::EstablishedInLoop,this)); }
        //发送数据，将数据放到发送缓冲区，并启动写事件监控
        void Send(const char* data,ssize_t len)
        {
            //外界传入的data，可能是个临时的空间，我们现在只是把发送操作压入了任务池，有可能并没有被立即执行
            //因此有可能执行的时候，data指向的空间有可能已经被释放了。
            Buffer buf;
            buf.WriteAndPush(data,len);
            _loop->RunInLoop(std::bind(&Connection::SendInLoop,this,std::move(buf)));
        }
        //提供给组件使用者的关闭接口--并不实际关闭，需要判断有没有数据待处理
        void Shutdown() { _loop->RunInLoop(std::bind(&Connection::ShutdownInLoop,this)); }
        void Release() { _loop->QueueInLoop(std::bind(&Connection::ReleaseInLoop,this)); }
        //启动非活跃销毁，并定义多长时间无通信就是非活跃，添加定时任务
        void EnableInactiveRelease(int sec) { _loop->RunInLoop(std::bind(&Connection::EnableInactiveReleaseInLoop,this,sec)); }
        // 取消非活跃销毁
        void CancelInactiveRelease() { _loop->RunInLoop(std::bind(&Connection::CancelInactiveReleaseInLoop,this)); }
        //切换协议---重置上下文以及阶段性回调处理函数 -- 而是这个接口必须在EventLoop线程中立即执行
        //防备新的事件触发后，处理的时候，切换任务还没有被执行--会导致数据使用原协议处理了。
        void Upgrade(const Any &context, const ConnectedCallback &conn, const MessageCallback &msg, 
                     const ClosedCallback &closed, const AnyEventCallback &event) 
        {
            _loop->AssertInLoop();
            _loop->RunInLoop(std::bind(&Connection::UpgradeInLoop, this, context, conn, msg, closed, event));
        }
};

class Acceptor 
{
    private:
        Socket _socket; //用于创建监听套接字
        EventLoop* _loop; //用于对监听套接字进行事件监控
        Channel _channel; //用来管理监听套接字触发事件后的回调函数

        using AcceptCallback = std::function<void(int)>;
        AcceptCallback _accept_callback; // 获取新链接后需要调用的函数
    private:
        //监听套接字的读事件回调处理函数--用来获取新连接，调用_accept_callback函数进行新连接处理
        void HandleRead()
        {
            int newfd = _socket.Accept();
            if(newfd < 0)
            {
                // 获取失败，直接返回
                return;
            }
            if(_accept_callback) _accept_callback(newfd);
        }
        //创建服务端连接
        //1. 创建套接字，2. 绑定地址，3. 开始监听，4. 设置非阻塞， 5. 启动地址重用
        int CreateServer(int port)
        {
            bool ret = _socket.CreateServer(port);
            assert(ret == true);
            return _socket.Fd();
        }
    public:
        //注意：
        /*不能将启动读事件监控，放到构造函数中，必须在设置回调函数后，再去启动*/
        /*否则有可能造成启动监控后，立即有事件，处理的时候，回调函数还没设置：新连接得不到处理，且资源泄漏*/
    Acceptor(EventLoop* loop,int port) : _socket(CreateServer(port)),_loop(loop),
            _channel(loop,_socket.Fd())
        {
            // 给_channel设置好处理新连接的回调函数
            _channel.SetReadCallback(std::bind(&Acceptor::HandleRead,this));
        }
        void SetAcceptCallback(const AcceptCallback& cb) { _accept_callback = cb; }
        //记得设置好_accept_callback再进行监听
        void Listen() { _channel.EnableRead(); }
};

class TcpServer
{
    private:
        int _port;
        uint64_t _next_id; // 自动增长的连接id
        int _timeout; // 规定多长时间无通信后进行非活跃连接的销毁
        bool _enable_inactive_release; // 是否启动了非活跃连接的销毁，默认为不销毁
        EventLoop _baseloop; // 主线程的EventLoop对象，负责监听
        Acceptor _acceptor; // 用来管理监听套接字的
        LoopThreadPool _pool; // 从属线程的线程池
        std::unordered_map<uint64_t,PtrConnection> _conns; // 管理所有连接的shared_ptr对象
    
        using ConnectedCallback = std::function<void(const PtrConnection&)>;
        using MessageCallback = std::function<void(const PtrConnection&, Buffer&)>;
        using ClosedCallback = std::function<void(const PtrConnection&)>;
        using AnyEventCallback = std::function<void(const PtrConnection&)>;
        using Functor = std::function<void()>;
        ConnectedCallback _connected_callback;
        MessageCallback _message_callback;
        ClosedCallback _closed_callback;
        AnyEventCallback _event_callback;
    private:
        // 添加定时任务
        void RunAfterInLoop(const Functor& task,int delay)
        {
            _next_id++;
            _baseloop.TimerAdd(_next_id,delay,task);
        }
        // 为新连接构造一个Connection进行管理
        void NewConnection(int fd)
        {
            _next_id++;
            PtrConnection conn(new Connection(_pool.NextLoop(),_next_id,fd));
            conn->SetMessageCallback(_message_callback);
            conn->SetClosedCallback(_closed_callback);
            conn->SetConnectedCallback(_connected_callback);
            conn->SetAnyEventCallback(_event_callback);
            conn->SetSrvClosedCallback(std::bind(&TcpServer::RemoveConnection, this, std::placeholders::_1));
            if (_enable_inactive_release) conn->EnableInactiveRelease(_timeout);//启动非活跃超时销毁
            conn->Established();//就绪初始化
            _conns.insert(std::make_pair(_next_id, conn));
        }
        // 从服务端删除连接信息，也就是从哈希表_conns中删除
        void RemoveConnectionInLoop(const PtrConnection& conn)
        {
            int id = conn->Id();
            if(_conns.find(id) != _conns.end())
            {
                _conns.erase(id);
            }
        }
        // 从管理Connection的_conns中移除连接信息
        void RemoveConnection(const PtrConnection& conn)
        {
            _baseloop.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop,this,conn));
        }
    public:
        TcpServer(int port) :
            _port(port),
            _next_id(0),
            _timeout(0),
            _enable_inactive_release(false),
            _acceptor(&_baseloop,port),
            _pool(&_baseloop)
        {
            _acceptor.SetAcceptCallback(std::bind(&TcpServer::NewConnection,this,std::placeholders::_1));
            _acceptor.Listen(); // 将监听套接字挂到_baseloop上
        }
        void SetThreadCount(int count) { return _pool.SetThreadCount(count); }
        void SetConnectedCallback(const ConnectedCallback&cb) { _connected_callback = cb; }
        void SetMessageCallback(const MessageCallback&cb) { _message_callback = cb; }
        void SetClosedCallback(const ClosedCallback&cb) { _closed_callback = cb; }
        void SetAnyEventCallback(const AnyEventCallback&cb) { _event_callback = cb; }
        void EnableInactiveRelease(int timeout) { _timeout = timeout; _enable_inactive_release = true; }

        //用于添加一个定时任务
        void RunAfter(const Functor &task, int delay)
        {
            _baseloop.RunInLoop(std::bind(&TcpServer::RunAfterInLoop,this,task,delay));
        }
        void Start()
        {
            _pool.Create();
            _baseloop.Start();
        }
};

void Channel::Remove() { return _loop->RemoveEvent(this); }
void Channel::Update() { return _loop->UpdateEvent(this); }
void TimerWheel::TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb) {
    _loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop, this, id, delay, cb));
}
//刷新/延迟定时任务
void TimerWheel::TimerRefresh(uint64_t id) {
    _loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop, this, id));
}
void TimerWheel::TimerCancel(uint64_t id) {
    _loop->RunInLoop(std::bind(&TimerWheel::TimerCancelInLoop, this, id));
}

// 当对方的连接已经断开的时候，我们如果还向对方发送数据时，就会触发SIGPIPE信号，导致程序异常
// 这个类的作用就是为了在服务启动的时候调用它的构造函数
// 这个这个函数的作用是为了屏蔽SIGPIPE信号
class NetWork 
{
    public:
        NetWork()
        {
            DBG_LOG("SIGPIPE INIT");
            signal(SIGPIPE, SIG_IGN);
        }
};
static NetWork nw;
//#endif